﻿namespace Centido.Core.Test
{
    using System;
    using System.Data.Common;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    ///   Testing working with users.
    /// </summary>
    [TestClass]
    public class UserTest
    {
        /// <summary>
        ///   The current domain name.
        /// </summary>
        public const string DomainName = "FullAdminRights";

        /// <summary>
        ///   The current domain.
        /// </summary>
        private Domain _domain;


        /// <summary>
        ///   Initializes a test.
        /// </summary>
        [TestInitialize]
        public void TestInitialize()
        {
            _domain = Domain.Build(DomainConfiguration.Load(DomainName));
            _domain.HasRecycleBin = new Random(Environment.TickCount).Next() % 2 == 1;

            _domain.DeleteAllUnits();
            _domain.DeleteAllRoles();
            _domain.DeleteAllUsers();
        }


        /// <summary>
        ///   Cleans a test up.
        /// </summary>
        [TestCleanup]
        public void TestCleanup()
        {
            _domain.DeleteAllUnits();
            _domain.DeleteAllRoles();
            _domain.DeleteAllUsers();
        }


        /// <summary>
        ///   Creating a user.
        /// </summary>
        [TestMethod]
        public void CreatingUser()
        {
            var initialUserCount = _domain.Users.Count();
            var initialPrincipalCount = _domain.Principals.Count();

            // Creating new user
            var userName = StringProperty.RandomIdentifier();

            var user = _domain.AddUser(userName, StringProperty.RandomPassword());

            Assert.IsNotNull(user);
            Assert.AreEqual(user.Name, userName.ToLower());
            
            Assert.AreEqual(_domain.Users.Count(), initialUserCount + 1);
            Assert.AreEqual(_domain.Users.Count(u => u.Name == userName.ToLower()), 1);
            Assert.IsTrue(user.Exists());

            Assert.AreEqual(_domain.Principals.Count(), initialPrincipalCount + 1);
            Assert.AreEqual(_domain.Principals.Count(p => p.Name == userName.ToLower()), 1);

            Assert.IsNotNull(_domain.GetUser(userName));
            Assert.AreEqual(_domain.GetUser(userName).Name, user.Name);
        }


        /// <summary>
        ///   Checking that user name is trimmed and lowered.
        /// </summary>
        [TestMethod]
        public void CheckingThatUserNameIsTrimmedAndLowered()
        {
            var userName = "\t " + StringProperty.RandomIdentifier().ToUpper();

            var user = _domain.AddUser(userName, StringProperty.RandomPassword());

            Assert.AreEqual(user.Name, userName.Trim().ToLower());
        }


        /// <summary>
        ///   Passing null user name when creating a user.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingNullUserNameWhenCreatingUser()
        {
            _domain.AddUser(null, "sdsd");
        }


        /// <summary>
        ///   Passing non-identifier as user name when creating a user.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingNonIdentifierUserNameWhenCreatingUser()
        {
            _domain.AddUser("1a", "sdsd");
        }


        /// <summary>
        ///   Passing keyword as user name when creating a user.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingKeywordUserNameWhenCreatingUser()
        {
            _domain.AddUser("select", "as");
        }


        /// <summary>
        ///   Passing too long user name when creating user.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingTooLongUserNameWhenCreatingUser()
        {
            _domain.AddUser(StringProperty.TooLongIdentifier('a'), "a");
        }


        /// <summary>
        ///   Creating a duplicate user.
        /// </summary>
        [TestMethod]
        public void CreatingDuplicateUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            try
            {
                _domain.AddUser(user.Name, StringProperty.RandomPassword());
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.AddingUserWithDuplicateName);
                return;
            }

            Assert.Fail();
        }


        /// <summary>
        ///   Creating an existing database user with a new password.
        /// </summary>
        [TestMethod]
        public void CreatingExistingDbUserWithNewPassword()
        {
            var userName = StringProperty.RandomIdentifier();
            var oldUserPassword = StringProperty.RandomPassword();
            var user = _domain.AddUser(userName, oldUserPassword);

            _domain.Logon(userName, oldUserPassword);

            // Dropping the user
            user.Delete();

            // Creating a user with the same name but different password
            var newUserPassword = StringProperty.RandomPassword();

            _domain.AddUser(userName, newUserPassword);

            _domain.Logon(userName, newUserPassword);
        }


        /// <summary>
        ///   Creating an existing database user with the same password.
        /// </summary>
        [TestMethod]
        public void CreatingExistingDbUserWithSamePassword()
        {
            var userName = StringProperty.RandomIdentifier();
            var oldUserPassword = StringProperty.RandomPassword();
            var user = _domain.AddUser(userName, oldUserPassword);

            _domain.Logon(userName, oldUserPassword);

            // Dropping the user
            user.Delete();

            // Creating a user with the same name
            _domain.AddUser(userName);

            _domain.Logon(userName, oldUserPassword);
        }


        /// <summary>
        ///   Creating a user not specifying a password.
        /// </summary>
        [TestMethod]
        public void CreatingUserNotSpecifyingPassword()
        {
            var userName = StringProperty.RandomIdentifier();
            
            _domain.AddUser(userName);

            _domain.Logon(userName, RestoreTask.DefaultUserPassword);
        }


        /// <summary>
        ///   Reading and writing the user display name.
        /// </summary>
        [TestMethod]
        public void ReadingAndWritingUserDisplayName()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.IsNull(user.DisplayName);

            //  Setting display name
            var userDisplayName = StringProperty.StandardValue('A');

            user.DisplayName = userDisplayName;

            Assert.AreEqual(user.DisplayName, userDisplayName);

            //  Setting display name to null
            user.DisplayName = null;

            Assert.IsNull(user.DisplayName);
        }


        /// <summary>
        ///   Setting a too long user display name.
        /// </summary>
        [TestMethod]
        public void SettingTooLongUserDisplayName()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            try
            {
                user.DisplayName = StringProperty.TooLongStandardValue('A');
            }
            catch (DbException)
            {
                Assert.IsNull(user.DisplayName);
                return;
            }

            Assert.Fail();
        }


        /// <summary>
        ///   Adding a user in a unit.
        /// </summary>
        [TestMethod]
        public void AddingUserInUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            Assert.AreEqual(user.Units.Count(), 0);
            Assert.AreEqual(unit.Users.Count(), 0);
            Assert.IsFalse(unit.ContainsUser(user));

            unit.AddUser(user);

            Assert.AreEqual(user.Units.Count(), 1);
            Assert.AreEqual(unit.Users.Count(), 1);
            Assert.IsTrue(unit.ContainsUser(user));

            var anotherUnit = _domain.AddUnit(StringProperty.RandomIdentifier());

            Assert.IsFalse(anotherUnit.ContainsUser(user));

            anotherUnit.AddUser(user);

            Assert.AreEqual(user.Units.Count(), 2);
            Assert.AreEqual(unit.Users.Count(), 1);
            Assert.AreEqual(anotherUnit.Users.Count(), 1);
            Assert.IsTrue(anotherUnit.ContainsUser(user));
        }

        /// <summary>
        ///   Passing null when adding a user in a unit.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingNullWhenAddingUserInUnit()
        {
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.AddUser(user: null);
        }

        /// <summary>
        ///   Adding a duplicate user in a unit.
        /// </summary>
        [TestMethod]
        public void AddingDuplicateUserInUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.AddUser(user);

            try
            {
                unit.AddUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.AddingDuplicateUserUnit);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Adding a user in a nonexistent unit.
        /// </summary>
        [TestMethod]
        public void AddingUserInNonexistentUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.Delete();

            try
            {
                unit.AddUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UnitWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Adding a nonexistent user in a unit.
        /// </summary>
        [TestMethod]
        public void AddingNonexistentUserInUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            user.Delete();

            try
            {
                unit.AddUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Removing a user from a unit.
        /// </summary>
        [TestMethod]
        public void RemovingUserFromUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());
            var anotherUnit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.AddUser(user);
            anotherUnit.AddUser(user);

            Assert.AreEqual(user.Units.Count(), 2);
            Assert.AreEqual(unit.Users.Count(), 1);
            Assert.AreEqual(anotherUnit.Users.Count(), 1);
            Assert.IsTrue(unit.ContainsUser(user));
            Assert.IsTrue(anotherUnit.ContainsUser(user));

            unit.RemoveUser(user);

            Assert.AreEqual(user.Units.Count(), 1);
            Assert.AreEqual(unit.Users.Count(), 0);
            Assert.AreEqual(anotherUnit.Users.Count(), 1);
            Assert.IsFalse(unit.ContainsUser(user));
            Assert.IsTrue(anotherUnit.ContainsUser(user));

            anotherUnit.RemoveUser(user);

            Assert.AreEqual(user.Units.Count(), 0);
            Assert.AreEqual(unit.Users.Count(), 0);
            Assert.AreEqual(anotherUnit.Users.Count(), 0);
            Assert.IsFalse(unit.ContainsUser(user));
            Assert.IsFalse(anotherUnit.ContainsUser(user));
        }

        /// <summary>
        ///   Removing a not added user from unit.
        /// </summary>
        [TestMethod]
        public void RemovingNonAddedUserFromUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            try
            {
                unit.RemoveUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserInUnitWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Removing a nonexistent user from a unit.
        /// </summary>
        [TestMethod]
        public void RemovingNonexistentUserFromUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            user.Delete();

            try
            {
                unit.RemoveUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Removing a user from a nonexistent unit.
        /// </summary>
        [TestMethod]
        public void RemovingUserFromNonexistentUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.Delete();

            try
            {
                unit.RemoveUser(user);
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UnitWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Deleting a unit that has users inside.
        /// </summary>
        [TestMethod]
        public void DeletingUnitThatHasUsersInside()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.AddUser(user);

            Assert.AreEqual(user.Units.Count(), 1);

            unit.Delete();

            Assert.AreEqual(user.Units.Count(), 0);
        }

        /// <summary>
        ///   Deleting a user that was inside a unit.
        /// </summary>
        [TestMethod]
        public void DeletingUserThatWasInsideUnit()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());
            var unit = _domain.AddUnit(StringProperty.RandomIdentifier());

            unit.AddUser(user);

            Assert.AreEqual(unit.Users.Count(), 1);

            user.Delete();

            Assert.AreEqual(unit.Users.Count(), 0);
        }

        /// <summary>
        ///   Reading and writing the CanLogin property.
        /// </summary>
        [TestMethod]
        public void ReadingAndWritingUserCanLogin()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.IsTrue(user.CanLogon);

            // Setting CanLogin to false (twice)
            user.CanLogon = false;
            user.CanLogon = false;

            Assert.IsFalse(user.CanLogon);

            // Setting CanLogin to true
            user.CanLogon = true;

            Assert.IsTrue(user.CanLogon);
        }

        /// <summary>
        ///   Changing the CanLogin property of a nonexistent user.
        /// </summary>
        [TestMethod]
        public void ChangingCanLoginOfNonexistentUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.Delete();

            try
            {
                user.CanLogon = true;
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Changing the CanLogin property of the current user.
        /// </summary>
        [TestMethod]
        public void ChangingCurrentUserCanLogin()
        {
            foreach (var user in _domain.Users)
                if (user.Name == _domain.CurrentUser.Name)
                {
                    try
                    {
                        user.CanLogon = false;
                    }
                    catch (DbException e)
                    {
                        Assert.AreEqual(e.GetErrorCode(), DbErrorCode.ChangingCurrentUserCanLogon);
                        return;
                    }

                    Assert.Fail();
                }
        }

        /// <summary>
        ///   Checking the user login ability.
        /// </summary>
        [TestMethod]
        public void CheckingAllowedUserLogin()
        {
            var userPassword = StringProperty.RandomPassword();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), userPassword);

            // Setting CanLogin to true
            user.CanLogon = true;

            var domain = _domain.Logon(user.Name, userPassword);

            // Logging in
            Assert.AreEqual(domain.CurrentUser.Name, user.Name);
        }

        /// <summary>
        ///   Checking the locked user login ability.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(DbException), AllowDerivedTypes = true)]
        public void CheckingNotAllowedUserLogin()
        {
            var userPassword = StringProperty.RandomPassword();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), userPassword);

            // Setting CanLogin to false
            user.CanLogon = false;

            // Logging in
            _domain.Logon(user.Name, userPassword);
        }

        /// <summary>
        ///   Checking that a user with a wrong password cannot login.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(DbException), AllowDerivedTypes = true)]
        public void CheckingThatUserWithWrongPasswordCannotLogin()
        {
            var userPassword = StringProperty.RandomPassword();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), userPassword);

            // Setting CanLogin to true
            user.CanLogon = true;

            // Logging in
            _domain.Logon(user.Name, StringProperty.RandomPassword());
        }

        /// <summary>
        ///   Reading and writing the CanChangeSchema property.
        /// </summary>
        [TestMethod]
        public void ReadingAndWritingUserCanChangeSchema()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.IsFalse(user.CanChangeSchema);

            // Setting CanChangeSchema to true (twice)
            user.CanChangeSchema = true;
            user.CanChangeSchema = true;

            Assert.IsTrue(user.CanChangeSchema);

            // Setting CanChangeSchema to false (twice)
            user.CanChangeSchema = false;
            user.CanChangeSchema = false;

            Assert.IsFalse(user.CanChangeSchema);
        }

        /// <summary>
        ///   Changing the CanChangeSchema proeprty of a nonexistent user.
        /// </summary>
        [TestMethod]
        public void ChangingCanChangeSchemaOfNonexistentUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.Delete();

            try
            {
                user.CanChangeSchema = true;
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }


        /// <summary>
        ///   Bug fix: changing CanChangeSchema property when the recycle bin is disabled.
        /// </summary>
        [TestMethod]
        public void ChangingCanChangeSchemaWhenRecycleBinIsDisabled()
        {
            // Creating at least one table
            _domain.AddTable(StringProperty.RandomIdentifier());

            // Disabling the recycle bin
            _domain.HasRecycleBin = false;

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.IsFalse(user.CanChangeSchema);

            // Setting CanChangeSchema to true
            user.CanChangeSchema = true;

            Assert.IsTrue(user.CanChangeSchema);

            // Setting CanChangeSchema to false
            user.CanChangeSchema = false;

            Assert.IsFalse(user.CanChangeSchema);
        }

        /// <summary>
        ///   Reading and writing the CanChangeSecurity property.
        /// </summary>
        [TestMethod]
        public void ReadingAndWritingCanChangeSecurity()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.IsFalse(user.CanChangeSchema);

            // Setting CanChangeSecurity to true (twice)
            user.CanChangeSecurity = true;
            user.CanChangeSecurity = true;

            Assert.IsTrue(user.CanChangeSecurity);

            // Setting CanChangeSecurity to false (twice)
            user.CanChangeSecurity = false;
            user.CanChangeSecurity = false;

            Assert.IsFalse(user.CanChangeSecurity);
        }

        /// <summary>
        ///   Changing the CanChangeSecurity property of a nonexistent user.
        /// </summary>
        [TestMethod]
        public void ChangingCanChangeSecurityOfNonexistentUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.Delete();

            try
            {
                user.CanChangeSecurity = true;
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Changing the CanChangeSecurity property of the current user.
        /// </summary>
        [TestMethod]
        public void ChangingCurrentUserCanChangeSecurity()
        {
            foreach (var user in _domain.Users)
                if (user.Name == _domain.CurrentUser.Name)
                {
                    try
                    {
                        user.CanChangeSecurity = false;
                    }
                    catch (DbException e)
                    {
                        Assert.AreEqual(e.GetErrorCode(), DbErrorCode.ChangingCurrentUserCanChangeSecurity);
                        return;
                    }

                    Assert.Fail();
                }
        }

        /// <summary>
        ///   Changing the CanChangeSecurity property from an ordinary user.
        /// </summary>
        [TestMethod]
        public void ChangingCanChangeSecurityByOdrinaryUser()
        {
            var user1Password = StringProperty.RandomPassword();
            var user1 = _domain.AddUser(StringProperty.RandomIdentifier(), user1Password);
            var user2 = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            var domain = _domain.Logon(user1.Name, user1Password);

            try
            {
                domain.GetUser(user2.Name).CanChangeSecurity = true;
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.InsufficientPrivilegesToChangeSecurityPermissions);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Deleting a user.
        /// </summary>
        [TestMethod]
        public void DeletingUserByReference()
        {
            var initialUserCount = _domain.Users.Count();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.AreEqual(_domain.Users.Count(), initialUserCount + 1);

            // Deleting the user
            _domain.DeleteUser(user);

            Assert.AreEqual(_domain.Users.Count(), initialUserCount);
            Assert.IsNull(_domain.GetUser(user.Name));
            Assert.IsFalse(user.Exists());
        }

        /// <summary>
        ///   Deleting a user by name.
        /// </summary>
        [TestMethod]
        public void DeletingUserByName()
        {
            var initialUserCount = _domain.Users.Count();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            Assert.AreEqual(_domain.Users.Count(), initialUserCount + 1);

            // Deleting the user
            _domain.DeleteUser(user.Name);

            Assert.AreEqual(_domain.Users.Count(), initialUserCount);
            Assert.IsNull(_domain.GetUser(user.Name));
            Assert.IsFalse(user.Exists());
        }

        /// <summary>
        ///   Deleting a deleted user.
        /// </summary>
        [TestMethod]
        public void DeletingDeletedUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.Delete();

            try
            {
                user.Delete();
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Changing a property of a deleted user.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(DbException), AllowDerivedTypes = true)]
        public void ChangingPropertyOfDeletedUser()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            // Deleting the user
            user.Delete();

            user.DisplayName = StringProperty.StandardValue('a');
        }

        /// <summary>
        ///   Deleting the current user.
        /// </summary>
        [TestMethod]
        public void DeletingCurrentUser()
        {
            foreach (var user in _domain.Users)
                if (user.Name == _domain.CurrentUser.Name)
                {
                    try
                    {
                        user.Delete();
                    }
                    catch (DbException e)
                    {
                        Assert.AreEqual(e.GetErrorCode(), DbErrorCode.DeletingCurrentUser);
                        return;
                    }

                    Assert.Fail();
                }
        }

        /// <summary>
        ///   Changing the user password.
        /// </summary>
        [TestMethod]
        public void ChangingUserPassword()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.ChangePassword(StringProperty.RandomPassword());
        }

        /// <summary>
        ///   Changing a nonexistent user password.
        /// </summary>
        [TestMethod]
        public void ChangingNonexistentUserPassword()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.Delete();

            try
            {
                user.ChangePassword(StringProperty.RandomPassword());
            }
            catch (DbException e)
            {
                Assert.AreEqual(e.GetErrorCode(), DbErrorCode.UserWasNotFound);
                return;
            }

            Assert.Fail();
        }

        /// <summary>
        ///   Passing null when changing the user password.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingNullWhenChangingUserPassword()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.ChangePassword(null);
        }

        /// <summary>
        ///   Passing empty string when changing the user password.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException), AllowDerivedTypes = true)]
        public void PassingEmptyStringWhenChangingUserPassword()
        {
            var user = _domain.AddUser(StringProperty.RandomIdentifier(), StringProperty.RandomPassword());

            user.ChangePassword("\t ");
        }

        /// <summary>
        ///   Logging in with a new password.
        /// </summary>
        [TestMethod]
        public void LoggingInWithNewPassword()
        {
            var oldPassword = StringProperty.RandomPassword();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), oldPassword);

            var newPassword = StringProperty.RandomPassword();

            user.ChangePassword(newPassword);

            // Logging in
            _domain.Logon(user.Name, newPassword);
        }

        /// <summary>
        ///   Logging in with an old password.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(DbException), AllowDerivedTypes = true)]
        public void LoggingInWithOldPassword()
        {
            var oldPassword = StringProperty.RandomPassword();

            var user = _domain.AddUser(StringProperty.RandomIdentifier(), oldPassword);

            var newPassword = StringProperty.RandomPassword();

            user.ChangePassword(newPassword);

            // Logging in
            _domain.Logon(user.Name, oldPassword);
        }
    }
}